package com.viknix.threadpool.manager.autoconfigure;

import com.viknix.threadpool.manager.client.message.MessageReceiver;
import com.viknix.threadpool.manager.client.util.PropertySourcesUtils;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.viknix.threadpool.manager.client.constant.PropertyKeyConst.*;

/**
 * @Author: Dongqi
 * @Date: 2021/10/21 13:34
 * @Version 1.0
 * @Description:
 */
@Data
@ConfigurationProperties(prefix = TpmConfigProperties.PREFIX)
public class TpmConfigProperties {

    public static final String PREFIX = "spring.tpm.config";

    @Autowired
    private transient Environment environment;

    private static final Pattern PATTERN = Pattern.compile("-(\\w)");

    /**
     * 服务端地址
     */
    private String serverAddr;

    /**
     * 客户端命名空间
     */
    private String namespace;

    /**
     * 客户端项目编号
     */
    private String projectId;

    /**
     * 是否打印 banner
     */
    private boolean banner = true;

    /**
     * 报警间隔时间
     */
    private Long period;

    /**
     * 通知接收者
     */
    private List<MessageReceiver> messageReceivers;

    /**
     * 为 configService 组装属性。
     *
     * @return properties
     */
    public Properties assembleConfigServiceProperties() {
        Properties properties = new Properties();
        properties.put(SERVER_ADDR, Objects.toString(this.serverAddr, ""));
        properties.put(ENCODE, Objects.toString(this.encode, ""));
        properties.put(NAMESPACE, Objects.toString(this.namespace, ""));
        properties.put(ACCESS_KEY, Objects.toString(this.accessKey, ""));
        properties.put(SECRET_KEY, Objects.toString(this.secretKey, ""));
        properties.put(CONTEXT_PATH, Objects.toString(this.contextPath, ""));
        properties.put(CLUSTER_NAME, Objects.toString(this.clusterName, ""));
        properties.put(MAX_RETRY, Objects.toString(this.maxRetry, ""));
        properties.put(CONFIG_LONG_POLL_TIMEOUT,
                Objects.toString(this.configLongPollTimeout, ""));
        properties.put(CONFIG_RETRY_TIME, Objects.toString(this.configRetryTime, ""));
        String endpoint = Objects.toString(this.endpoint, "");
        if (endpoint.contains(":")) {
            int index = endpoint.indexOf(":");
            properties.put(ENDPOINT, endpoint.substring(0, index));
            properties.put(ENDPOINT_PORT, endpoint.substring(index + 1));
        } else {
            properties.put(ENDPOINT, endpoint);
        }
        enrichTpmConfigProperties(properties);
        return properties;
    }

    private void enrichTpmConfigProperties(Properties tpmConfigProperties) {
        // 获取 bootstrap.yml 中关于 tpm 的配置信息
        Map<String, Object> properties = PropertySourcesUtils
                .getSubProperties((ConfigurableEnvironment) environment, PREFIX);
        properties.forEach((k, v) -> tpmConfigProperties.putIfAbsent(resolveKey(k),
                String.valueOf(v)));
    }

    private String resolveKey(String key) {
        Matcher matcher = PATTERN.matcher(key);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * encode for tpm config content.
     */
    private String encode;

    /**
     * access key for namespace.
     */
    private String accessKey;

    /**
     * secret key for namespace.
     */
    private String secretKey;

    /**
     * context path for tpm config server.
     */
    private String contextPath;

    /**
     * tpm config cluster name.
     */
    private String clusterName;

    /**
     * tpm maximum number of tolerable server reconnection errors.
     */
    private String maxRetry;

    /**
     * tpm get config long poll timeout.
     */
    private String configLongPollTimeout;

    /**
     * tpm get config failure retry time.
     */
    private String configRetryTime;

    /**
     * endpoint for Tpm, the domain name of a service, through which the server address
     * can be dynamically obtained.
     */
    private String endpoint;
}
